# -*- coding:utf-8 -*-
from threading import *
from HTCPServer import *
from HTCPDevice import *
import socket, traceback, os, sys, struct
import qutils, qcfg, time


K_DID_LEN = 32

class HTCPSrvWater(HTCPServer):
	# Command
	WATER_CMD_VER     	= 0x01
	WATER_CMD_START     = 0x02
	WATER_CMD_STOP      = 0x03
	WATER_CMD_VALUE    	= 0x04
	WATER_CMD_STATUS    = 0x05
	WATER_CMD_DID    	= 0x06
	WATER_CMD_IDREAD    = 0x07
	
	
	WATER_CMD_USER_START= 0x79
	WATER_CMD_USER_STOP = 0x78
	WATER_CMD_USER_STATUS= 0x77

	# Event
	WATER_EVT_HEARBEAT  = 0x81
	WATER_EVT_VALUE     = 0x82
	WATER_EVT_STATUS    = 0x83
	WATER_EVT_CARDID    = 0x84
	WATER_EVT_HISTORY   = 0x85


	def __init__(self):
		self.srvType = HTCPServer.HTCP_SERVER_TYPE_WATER
		self.devDict = {}

	def devCmdStart(self,aSock,aCmd,aTime):
		#if aTime > 0 :
		#	time.sleep(aTime)
		self.sendCommand(aSock, aCmd, "")

	def devCmdThread(self, aSock, aCmd, aTime) :
		#print "**************************",aTime
		#if aTime > 0 :
			#print "**************************"
		#	time.sleep(aTime)
		#print "&&&&&&&&&&&&&&&&&&&&&&&&--cmd"
		self.sendCommand(aSock, aCmd, "")
		#t = Thread(target=self.devCmdStart, args = [aSock, aCmd, aTime])
		#t.setDaemon(1)
		#t.start()

	def handleCommand(self, aSock, aAction, aRequest):
		print "********CMD:action=%x, request=%s" % (aAction, aRequest)
		if aAction == self.WATER_CMD_USER_START:
			print "CMD-USER-START"
			tmpLen = len(aRequest)
			if tmpLen < K_DID_LEN :
				self.sendResponse(aSock, aAction, struct.pack("!B", 0))
				return

			tmpDid,uid, = struct.unpack("!%ds%ds" % (K_DID_LEN, tmpLen-K_DID_LEN), aRequest)
			print "did=%s, uid=%s" % (tmpDid, uid)
			if not self.devDict.has_key(tmpDid) :
				self.sendResponse(aSock, aAction, struct.pack("!B", 0))
				return
		
			tmpDevice = self.devDict[tmpDid]
			tmpStatus = tmpDevice.isDevStart(uid)
			if tmpStatus == HTCPDevice.HTCP_DEV_START :
				#self.devCmdThread(aSock, self.WATER_CMD_START, tmpDevice.stime)
				qutils.rctLogger.info("tmpStatus == HTCPDevice.HTCP_DEV_START")
				self.devCmdThread(tmpDevice.sock, self.WATER_CMD_START, tmpDevice.stime)
				#self.sendCommand(tmpDevice.sock, self.WATER_CMD_START, "")
				self.sendResponse(aSock, aAction, '')
			else :
				self.sendResponse(aSock, aAction, struct.pack("!B", tmpStatus))
				
		elif aAction == self.WATER_CMD_USER_STOP:
			print "CMD-USER-STOP"
			tmpLen = len(aRequest)
			if tmpLen < K_DID_LEN :
				self.sendResponse(aSock, aAction, struct.pack("!B", 0))
				return
			tmpDid,uid, = struct.unpack("!%ds%ds" % (K_DID_LEN, tmpLen-K_DID_LEN), aRequest)
			print "did=%s, uid=%s" % (tmpDid, uid)
			if not self.devDict.has_key(tmpDid) :
				self.sendResponse(aSock, aAction, struct.pack("!B", 0))
				return
		
			tmpDevice = self.devDict[tmpDid]
			tmpStatus = tmpDevice.isDevStop(uid)
			if tmpStatus == HTCPDevice.HTCP_DEV_STOP :
				#self.sendCommand(tmpDevice.sock, self.WATER_CMD_STOP, "")
				self.devCmdThread(tmpDevice.sock, self.WATER_CMD_STOP, tmpDevice.etime)
				self.sendResponse(aSock, aAction, '')
			else :
				self.sendResponse(aSock, aAction, struct.pack("!B", tmpStatus))
		
		elif aAction == self.WATER_CMD_USER_STATUS:
			print "CMD-USER-STATUS"
			tmpLen = len(aRequest)
			if tmpLen < K_DID_LEN :
				self.sendResponse(aSock, aAction, struct.pack("!B", 0))
				return
				
			tmpDid,uid, = struct.unpack("!%ds%ds" % (K_DID_LEN, tmpLen-K_DID_LEN), aRequest)
			print "did=%s, uid=%s" % (tmpDid, uid)
			if not self.devDict.has_key(tmpDid) :
				self.sendResponse(aSock, aAction, struct.pack("!B", 0))
				return
				
			tmpDevice = self.devDict[tmpDid]
			self.sendResponse(aSock, aAction, struct.pack("!Bf", tmpDevice.status, tmpDevice.value))
		
		elif aAction == self.WATER_CMD_START :
			print "command START From Devices"
			tmpLen = len(aRequest)
			if tmpLen == 20 :
				did,val, = struct.unpack("!16sf", aRequest)
				tmpDid = qutils.hthex2str(did)
				print "did=%s, val=%f" % (tmpDid, val)
				if not self.devDict.has_key(tmpDid) :
					self.sendResponse(aSock, aAction, struct.pack("!B", 2))
					return
				tmpDevice = self.devDict[tmpDid]
				if tmpDevice :
					tmpDevice.setDevValue(aSock, val)

		elif aAction == self.WATER_CMD_STOP:
			print "command STOP From Devices"
			tmpLen = len(aRequest)
			if tmpLen == 20 :
				did,val, = struct.unpack("!16sf", aRequest)
				tmpDid = qutils.hthex2str(did)
				print "did=%s, val=%f" % (tmpDid, val)
				if not self.devDict.has_key(tmpDid) :
					self.sendResponse(aSock, aAction, struct.pack("!B", 2))
					return
				tmpDevice = self.devDict[tmpDid]
				if tmpDevice :
					tmpDevice.setDevValue(aSock, val)

	def handleEvent(self, aSock, aAction, aRequest):
		if aAction == self.WATER_EVT_HEARBEAT:
			print "WATER_EVT_HEARBEAT"
			print aSock
			if len(aRequest) != 18 : 
				print 'RSP-LEN-ERROR'
				self.sendResponse(aSock, aAction, "")
				return
				
			did,ver,status, = struct.unpack("!16sBB", aRequest)
			tmpDid = qutils.hthex2str(did)
			print "ver=%d, sta=%d, did=%s" %(ver, status, tmpDid)
			
			if self.devDict.has_key(tmpDid) :
				devWater = self.devDict[tmpDid]
				if devWater :
					print "has=%s" % tmpDid
					devWater.setDevStatus(aSock, status)
			else :
				print "no has=%s" % tmpDid
				self.devDict[tmpDid] = HTCPDevice(aSock, tmpDid, status)
				
		elif aAction == self.WATER_EVT_VALUE :
			print "WATER_EVT_VALUE"

			if len(aRequest) != 20 : 
				self.sendResponse(aSock, aAction, "")
				return

			did,value = struct.unpack("!16sf", aRequest)
			tmpDid = qutils.hthex2str(did)
			print "did=%s, val=%f" %(tmpDid, value)
			if not self.devDict.has_key(tmpDid) :
				self.sendResponse(aSock, aAction, "")
				return
			
			devWater = self.devDict[tmpDid]
			if devWater:
				devWater.setDevValue(aSock, value)
				              		
		elif aAction == self.WATER_EVT_STATUS:
			print "WATER_EVT_STATUS"
			if len(aRequest) != 17 : 
				self.sendResponse(aSock, aAction, "")
				return
				
			did,status = struct.unpack("!16sB", aRequest)
			tmpDid = qutils.hthex2str(did)
			print "did=%s, status=%d" %(tmpDid, status)
			if not self.devDict.has_key(tmpDid) :
				self.sendResponse(aSock, aAction, "")
				return
        	
			devWater = self.devDict[tmpDid]
			if devWater:
				devWater.setDevStatus(aSock, status)
				
		elif aAction == self.WATER_EVT_CARDID:
			print "WATER_EVT_CARDID"
			qutils.htprint("card", aRequest)
			tmpLen = len(aRequest)
			if tmpLen < 28 or tmpLen > 40:
				self.sendResponse(aSock, aAction, struct.pack("!B", 1))
				return
			did,cardstart,cardcmd,cardLen,ctype,cardnum,cardend = struct.unpack("!16s2sBHB%ds2s"%(tmpLen-24), aRequest)
			tmpCardNum = qutils.hthex2str(cardnum)
			tmpDid = qutils.hthex2str(did)
			print "did=%s,cs=%s,cmd=%d,cardlen=%d,ctype=%d,num=%s,end=%s" % (tmpDid,cardstart,cardcmd,cardLen,ctype,tmpCardNum,cardend)
			if self.devDict.has_key(tmpDid) :
				devWater = self.devDict[tmpDid]
				if devWater.isDevStatus() == HTCPDevice.HTCP_DEV_START :
					if devWater.isDevStop(tmpCardNum) == HTCPDevice.HTCP_DEV_STOP :
						self.devCmdThread(aSock, self.WATER_CMD_STOP, devWater.stime)
				else:
					if devWater.isDevStart(tmpCardNum) ==  HTCPDevice.HTCP_DEV_START :
						self.devCmdThread(aSock, self.WATER_CMD_START, devWater.etime)
			else :
				print "does not find dev=%s" % tmpDid
				
		elif aAction == self.WATER_EVT_HISTORY :
			print "WATER_EVT_HISTORY"
			
		self.sendResponse(aSock, aAction, "")

if __name__ == '__main__':
	print "**************************************************************************"
	print "********************                                   *******************"
	print "********************     HTCPWater For Dev v1.0.0      *******************"
	print "********************                                   *******************"
	print "********************           Tommy@2016              *******************"
	print "********************                                   *******************"
	print "**************************************************************************"
	print "SRVPORT=%s" % qcfg.HTCP_WATER_SRV_PORT
	srvaddr = ('', qcfg.HTCP_WATER_SRV_PORT)
	srvr = HTCPServer(srvaddr)
	srvr.registerServer(HTCPSrvWater())
	srvr.loop()